package com.bz.security;

import java.util.Collections;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.util.CollectionUtils;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import com.bz.model.UrlFilter;

/**
 * 安全配置类
 * 
 * @author Administrator
 *
 */
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private AuthAccessDeniedHandler         authaccessDeniedHandler;

    @Autowired
    private AuthenctiationFailureHandler    authenctiationFailureHandler;

    @Autowired
    private AuthenticationEntryPointHandler authenticationEntryPointHandler;

    @Autowired
    private UrlFilter                       urls;

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        String[] filtUrls = new String[] {};
        if (!CollectionUtils.isEmpty(urls.getUrls())) {
            filtUrls = urls.getUrls().toArray(new String[urls.getUrls().size()]);
        }

        http.headers().frameOptions().disable();
        http
            // CSRF禁用，因为不使用session
            .csrf().disable()
            // 认证失败处理类
            .exceptionHandling().authenticationEntryPoint(authenticationEntryPointHandler).and()
            // 基于token，所以不需要session
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
            .authorizeRequests()
            .antMatchers(filtUrls).permitAll()
            .anyRequest().authenticated() // 任何请求,登录后可以访问
            .and()
            .formLogin()
            .loginPage("/login")
            .defaultSuccessUrl("/web/index")
            // .successForwardUrl("/web/index")
            .failureUrl("/login?error")

            // 登录失败后跳转
            // .failureForwardUrl(forwardUrl)
            .failureHandler(authenctiationFailureHandler)
            .usernameParameter("username")
            .passwordParameter("password")
            .permitAll() // 登录页面用户任意访问
            .and()
            .exceptionHandling().accessDeniedHandler(authaccessDeniedHandler)
            .and()
            .logout().logoutUrl("/logout").logoutSuccessUrl("/web/index")
            .permitAll() // 注销行为任意访问
            .and()
            // 认证异常时返回
            .exceptionHandling().authenticationEntryPoint(authenticationEntryPointHandler) // 这里配置的为当未登录访问受保护资源时，返回json
            // .and().cors().configurationSource(corsConfigurationSource())
            .and()
            .headers()
            .disable();
        http.csrf().disable();
        http.cors().configurationSource(corsConfigurationSource())
            .and().csrf().disable(); // 允许跨域

        // 测试完后关闭poseMan
        http.httpBasic().and().csrf().disable();

        // 基于sessin，不需要杉木ion
        // http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

        // 拦截器

    }

    // 自定义认证方式
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // user Details Service验证
        // auth.authenticationProvider(myAuthenticationProvider);

    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder()).withUser("admin")
            .password(new BCryptPasswordEncoder().encode("admin")).roles("USER");
        // auth
        // .inMemoryAuthentication()
        // .withUser("user").password("password").roles("USER");
    }

    //
    @Override
    public void configure(WebSecurity web) throws Exception {
        // 解决静态资源被拦截的问题
        web.ignoring().antMatchers("/static/**");
        web.ignoring().antMatchers("/auth/**");
        // web.ignoring().antMatchers("/web/**");
        web.ignoring().antMatchers("/");
    }

    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.setAllowedMethods(Collections.singletonList("*"));
        corsConfiguration.setAllowedHeaders(Collections.singletonList("*"));
        corsConfiguration.setAllowedOrigins(Collections.singletonList("*"));
        corsConfiguration.setAllowCredentials(true);
        corsConfiguration.setMaxAge(3600L);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", corsConfiguration);
        return source;
    }
}